import math
from django.shortcuts import render, redirect
from app_01 import models
from django import forms # forms.ModelForm使用
from django.core.validators import RegexValidator ## 正则表达式模块
from django.core.exceptions import ValidationError ## raise抛出异常
from django.utils.safestring import mark_safe ### 字符串显示为安全字符串:page_string = mark_safe(''.join(page_str_list))


# Create your views here.
def pretty_list(request):
    ## 添加测试用的数据
    # for i in range(50):
    #     models.PrettyNum.objects.create(mobile='123456789', price='777777', level=4, status=2)

    ## 添加查询用的字典
    data_dict = {}
    search_data = request.GET.get('q','') ## 当url中？后面的参数q=有数值的时候，search_data会获取q的数据，
                                          ## 当q没有数据或着没有q=时，search_data=''
    # if search_data:
    #     data_dict['mobile__contains'] = search_data
    data_dict['mobile__contains'] = search_data
    # print(111111111,type(search_data),22222,search_data)

    ## 根据用户想要访问的页码，获取每个页面的起始和结束的位置
    page = int(request.GET.get('page',1))
    page_size = 10
    start = (page-1)*page_size
    end = page*page_size
    # 符合条件的数据的总条数
    total_count = models.PrettyNum.objects.filter(**data_dict).count()
    # 再根据page_size计算出总共的页数，计算的时候要向上取整
    total_page_count = math.ceil(total_count/page_size)

    queryset = models.PrettyNum.objects.filter(**data_dict).order_by('-id')[start:end] # 根据字段的值进行排序，带着负号是降序。获取列表中的索引的数据
    # if search_data == '':
    #     search_data = '5555555'
    #     print(333333333, type(search_data), 4444444, search_data)
    # level = models.PrettyNum.level_choices

    ### 只显示页码的前后5页。利用当前页-5或者当前页+5来实现。并且让开始和结束页码在正确的区间中，不会成为负数或者是大于总页码数
    plus = 5
    if page <= plus or page == '':
        start_page = 1
        if total_page_count < 2*plus:
            end_page = total_page_count
        else:
            end_page = 2*plus
    else:
        if (page+plus) > total_page_count:
            if total_page_count < 2*plus:
                start_page = 1
            else:
                start_page = total_page_count - 2*plus
            end_page = total_page_count
        else:
            start_page = page - plus
            end_page = page + plus



    ### 生成页码：把前端生成的代码放在后端，当作字符串。给字符串中的占位符赋好值后，再传递到前端页面对应的位置
    page_str_list = []
    ### 首页
    page_str_list.append('<li><a href="/pretty/list/?page={}">首页</a></li>'.format(1))

    ### 上一页
    if page > 1:
        prev = '<li><a href="/pretty/list/?page={}">上一页</a></li>'.format(page - 1)
    else:
        prev = '<li><a href="/pretty/list/?page={}">上一页</a></li>'.format(1)
    page_str_list.append(prev)

    ### 中间页码
    for i in range(start_page,end_page+1):
        if page == i:
            ele = '<li class="active"><a href="/pretty/list/?page={}">{}</a></li>'.format(i, i)
        else:
            ele = '<li><a href="/pretty/list/?page={}">{}</a></li>'.format(i,i)
        page_str_list.append(ele)

    ### 下一页
    if page < total_page_count:
        prev = '<li><a href="/pretty/list/?page={}">下一页</a></li>'.format(page + 1)
    else:
        prev = '<li><a href="/pretty/list/?page={}">下一页</a></li>'.format(total_page_count)
    page_str_list.append(prev)

    ### 尾页
    page_str_list.append('<li><a href="/pretty/list/?page={}">尾页</a></li>'.format(total_page_count))

    ### 跳转页面
    search_string = """
        <li>
                        <form style="float: left;margin-left: -1px" method="get">
                            <input name="page" style="position: relative;float: left;display:inline-block;width: 80px;border-radius: 0;"
                            type="text" class="form-control" placeholder="页码">
                            <button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
                        </form>
                    </li>
    """
    page_str_list.append(search_string)

    page_string = mark_safe(''.join(page_str_list)) ## 字符串标记为安全字符串，这样可以正常显示页码

    """ 前端生成页码的代码
    <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>
    <li class="active"><a href="/pretty/list/?page=1">1 <span class="sr-only">(current)</span></a></li>
    <li><a href="/pretty/list/?page=2">2</a></li>
    <li><a href="/pretty/list/?page=3">3</a></li>
    <li><a href="/pretty/list/?page=4">4</a></li>
    <li><a href="/pretty/list/?page=5">5</a></li>
    <li><a href="#" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>
    """

    return render(request,'pretty_list.html',
                  {'queryset':queryset,'search_data':search_data,'page_string':page_string})


class PrettyModelForm(forms.ModelForm):
    ##校验方式一：手动书写校验
    # mobile = forms.CharField(
    #     label='手机号',
    #     validators=[RegexValidator(r'^1[3-9]\d{9}$', '输入的手机号格式错误')] # 正则表达式可以写多个，都放在这个列表中
    # )
    class Meta:
        model = models.PrettyNum # 关联models.py中的表格
        fields = '__all__' # 可以用列表列出所有的列，也可以用这个来代表显示所有的列
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items(): # name是models.py中表PrettyNum中定义的字段的名字如：mobile,price,level等
                                              # name数据的作用是：可以通过比较只让那几个字段更改插件属性。如：if name == 'mobile': 。。。。。
                                             # field是列对象，里面包含列对象的样式等。
            if field.widget.attrs: # 判断是否存在插件的属性，如果存在就只把这俩属性class和placeholder更改，其余的保持不变
                field.widget.attrs['class'] = "form-control"
                field.widget.attrs['placeholder'] = field.label
            else: # 如果不存在插件属性，那么就直接赋值就可以。
                field.widget.attrs = {'class': "form-control",'placeholder': field.label}

    #### 校验方式二：利用字段的钩子方法。例如：利用手机号字段的钩子方法来验证手机号
    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile'] ## clean_data中保存着校验好的数据
        exists = models.PrettyNum.objects.filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError('手机号码已存在！')
        if len(txt_mobile) != 11:
            raise ValidationError('手机号码格式错误')
        return txt_mobile #校验通过的话就返回这个数据

def pretty_add(request):

    if request.method == 'GET':
        form = PrettyModelForm()
        return render(request,'pretty_add.html',{'form':form})
    form = PrettyModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')
    return render(request, 'pretty_add.html', {'form': form})


class PrettyEditModelForm(forms.ModelForm):
    ##校验方式一：手动书写校验
    # mobile = forms.CharField(
    #     label='手机号',
    #     validators=[RegexValidator(r'^1[3-9]\d{9}$', '输入的手机号格式错误')] # 正则表达式可以写多个，都放在这个列表中
    # )
    class Meta:
        model = models.PrettyNum # 关联models.py中的表格
        fields = '__all__' # 可以用列表列出所有的列，也可以用这个来代表显示所有的列
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items(): # name是models.py中表PrettyNum中定义的字段的名字如：mobile,price,level等
                                              # name数据的作用是：可以通过比较只让那几个字段更改插件属性。如：if name == 'mobile': 。。。。。
                                             # field是列对象，里面包含列对象的样式等。
            if field.widget.attrs: # 判断是否存在插件的属性，如果存在就只把这俩属性class和placeholder更改，其余的保持不变
                field.widget.attrs['class'] = "form-control"
                field.widget.attrs['placeholder'] = field.label
            else: # 如果不存在插件属性，那么就直接赋值就可以。
                field.widget.attrs = {'class': "form-control",'placeholder': field.label}

    #### 校验方式二：利用字段的钩子方法。例如：利用手机号字段的钩子方法来验证手机号
    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile'] ## clean_data中保存着校验好的数据
        idd = self.instance.pk ## pk是当前对象的primarykey，也就是id的值。获取当前对象指向的row_object，在下面的pretty_edit函数中已经通过
                             ## form = PrettyModelForm(data=request.POST,instance=row_object)，把对象row_object赋值给了instance
        exists = models.PrettyNum.objects.exclude(id=idd).filter(mobile=txt_mobile).exists() ## 排除自己的id意外，没有重复的
        if exists:
            raise ValidationError('手机号码已存在！')
        if len(txt_mobile) != 11:
            raise ValidationError('手机号码格式错误')
        return txt_mobile #校验通过的话就返回这个数据

def pretty_edit(request,nid):
    row_object = models.PrettyNum.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = PrettyEditModelForm(instance=row_object)
        return render(request,'pretty_edit.html',{'form':form})
    form = PrettyEditModelForm(data=request.POST,instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')
    return render(request, 'pretty_edit.html', {'form': form})


def pretty_delete(request,nid):
    models.PrettyNum.objects.filter(id=nid).delete()
    return redirect('/pretty/list/')

def admin_list(request):
    pass


